var colorPicker =        //名称可改
{
/*成员*/
    that: null,
    callback:null,
    part:null,
    rgb: null,
    hsl: null,
    hsv:null,
/*常量*/
    PickerCenterX: null,
    PickerCenterY: null,
    PickerLeftOffset: null,
    MaskTop: null,
    MaskRight: null,
    MaskBottom: null,
    MaskLeft: null,  
    MaskWidth: null,
    MaskHeight: null,
    CallbackDelay:200,
    /*变量*/
    hexDisplay: null,
    rgbInput: null,
    hslInput: null,
    hsvInput: null,
    mask: null,
    markerWheel: null,
    markerMask: null,
    color: null,
    mouseX:null,
    mouseY: null,
    partPosition:null,

/*接口*/
    /**
     * 初始化
     */
    initial:function(callback)
    {
        var picker=document.getElementById("colorPicker_picker");
        var pickerStyle = window.getComputedStyle(picker, null);
        this.PickerCenterX = parseInt(pickerStyle.height) * 0.5;
        this.PickerCenterY = parseInt(pickerStyle.width) * 0.5;
        this.PickerLeftOffset = picker.offsetLeft;
        this.MaskTop = parseInt(pickerStyle.height) *0.25;
        this.MaskRight = parseInt(pickerStyle.width) * 0.75;
        this.MaskBottom = parseInt(pickerStyle.height) * 0.75;
        this.MaskLeft = parseInt(pickerStyle.width) * 0.25;
        this.MaskWidth = parseInt(pickerStyle.width) * 0.5;
        this.MaskHeight = parseInt(pickerStyle.height) * 0.5;

        this.that = this;
        this.callback = callback;
        this.part=document.getElementById("colorPicker");       //成员初始化
        this.mask=document.getElementById("colorPicker_picker_mask");       
        this.markerWheel=document.getElementById("colorPicker_picker_markerWheel");
        this.markerMask=document.getElementById("colorPicker_picker_markerMask"); 
        this.color=document.getElementById("colorPicker_selected_color");
        this.hexDisplay=document.getElementById("colorPicker_selected_hex");
        this.rgbInput=document.getElementById("colorPicker_selected_rgb").getElementsByTagName("input");
        this.hslInput=document.getElementById("colorPicker_selected_hsl").getElementsByTagName("input");
        this.hsvInput=document.getElementById("colorPicker_selected_hsv").getElementsByTagName("input");
        this.rgb = new RGB(255,255,255);
        this.hsl = new HSL(0,1,1);
        this.hsv = new HSV(0,1,1);

        this.markerWheel.that=this;     //在markWheel对象内设置对此对象的引用
        this.markerMask.that = this;      //在markerMask对象内设置对此对象的引用
        this.mask.that = this;      //在mask对象内置对此对象的引用

        var that = this;

        this.mask.onmousedown = function (e)
        {
            that.partPosition = that.part.getBoundingClientRect();
            var x = e.clientX - that.partPosition.left - that.PickerLeftOffset;
            var y = e.clientY - that.partPosition.top;

            if (x < that.MaskLeft)
                x = that.MaskLeft;
            else if (x > that.MaskRight)
                x = that.MaskRight;
            if (y < that.MaskTop)
                y = that.MaskTop;
            else if (y > that.MaskBottom)
                y = that.MaskBottom;

            that.markerMask.style.left = x + "px";
            that.markerMask.style.top = y + "px";

            that.hsv.s = (x - that.MaskLeft) / that.MaskWidth;
            that.hsv.v = 1 - (y - that.MaskTop) / that.MaskHeight; 
            that.pickerActivate();

            return false;
        };

        this.markerWheel.onmousedown=function(e)     //事件：Wheel标记拖动
        {
            that.partPosition = that.part.getBoundingClientRect();
            that.markerWheel_handlerMouseMove(e);

            this.addEventListener("mousemove",that.markerWheel_handlerMouseMove);
            this.addEventListener("mouseup",that.markerWheel_handlerMouseUp);

            return false;
        };
        this.markerWheel.onmouseleave = this.markerWheel_handlerMouseUp;

        this.markerMask.onmousedown=function(e)      //事件：Mask标记拖动
        {
            that.mouseX=e.clientX;     //记录此次位置
            that.mouseY=e.clientY;

            this.addEventListener("mousemove", that.markerMask_handlerMouseMove);
            this.addEventListener("mouseup", that.markerMask_handlerMouseUp);

            return false;
        };
        this.markerMask.onmouseleave = this.markerMask_handlerMouseUp;

        var inputs=document.getElementById("colorPicker_selected").getElementsByTagName("input");
        for(var i=inputs.length-1;i>=0;i--)        
        {
            inputs[i].onkeypress=this.inputEnter;       //事件：输入回车
            inputs[i].onblur=this.inputBlur;        //事件：失去焦点
            inputs[i].onfocus = this.inputFocus;      //事件：获得焦点

            inputs[i].valueCheck = this.valueCheck;       //注册valueCheck函数
        }

        var input255=document.getElementsByClassName("ColorPicker_255");
        for (var i = 0; i < input255.length; i++)
        {           
            input255[i].checkValue = function ()     //值确认
            {
                var inputValue = parseInt(this.value);
                if (inputValue >= 0 && inputValue <= 255)
                {
                    this.value = inputValue.toString();
                    this.parentNode.activate();
                }
                else
                    this.value = this.valuePreserve;
            };

            input255[i].addEventListener("mousewheel",function(e)
            {
                if(document.activeElement.id==this.id)
                {
                    var value=parseFloat(this.value);
                    if(e.deltaY<0)
                    {
                        value+=1;
                        if(value>255)
                            value=255;
                    }
                    else
                    {
                        value-=1;
                        if(value<0)
                            value=0;
                    }

                    this.value=value;
                    this.parentNode.activate();
                }
            });
        }
        var input1=document.getElementsByClassName("ColorPicker_1");
        for (var i = 0; i < input1.length; i++)
        {
            input1[i].checkValue = function ()
            {
                var inputValue = parseFloat(this.value);
                if (inputValue >= 0 && inputValue <= 1)
                {
                    this.value = inputValue.toFixed(2).toString();
                    this.parentNode.activate();
                }
                else
                    this.value = this.valuePreserve;
            };

            input1[i].addEventListener("mousewheel",function(e)
            {
                if(document.activeElement.id==this.id)
                {
                    var value=parseFloat(this.value);
                    if(e.deltaY<0)
                    {
                        value+=0.01;
                        if(value>1)
                            value=1;
                    }
                    else
                    {
                        value-=0.01;
                        if(value<0)
                            value=0;
                    }

                    this.value=value;
                    this.parentNode.activate();
                }
            });
        }
        var input360 = document.getElementsByClassName("ColorPicker_360");
        for (var i = 0; i < input360.length; i++)
        {
            input360[i].checkValue = function ()
            {
                var inputValue = parseFloat(this.value);
                if (inputValue >= 0 && inputValue <= 359)
                {
                    this.value = inputValue.toFixed(2).toString();
                    this.parentNode.activate();
                }
                else
                    this.value = this.valuePreserve;
            };

            input360[i].addEventListener("mousewheel",function(e)
            {
                if(document.activeElement.id==this.id)
                {
                    var value=parseFloat(this.value);
                    if(e.deltaY<0)
                    {
                        value+=1;
                        if(value>359)
                            value=359;
                    }
                    else
                    {
                        value-=1;
                        if(value<0)
                            value=0;
                    }

                    this.value=value;
                    this.parentNode.activate();
                }
            });
        }

        document.getElementById("colorPicker_selected_rgb").activate=function()      //输入触发
        {
            that.rgb = new RGB(parseInt(that.rgbInput[0].value), parseInt(that.rgbInput[1].value), parseInt(that.rgbInput[2].value));
            that.hsl = that.rgb.toHSL();
            that.hsv = that.rgb.toHSV();

            that.changeColor();
            that.reposition();
        };
        document.getElementById("colorPicker_selected_hsl").activate=function()      //输入触发
        {
            that.hsl = new HSL(parseFloat(that.hslInput[0].value), parseFloat(that.hslInput[1].value), parseFloat(that.hslInput[2].value));
            that.rgb = that.hsl.toRGB();
            that.hsv = that.hsl.toHSV();

            that.changeColor();
            that.reposition();
        };
        document.getElementById("colorPicker_selected_hsv").activate=function()      //输入触发
        {
            that.hsv = new HSV(parseFloat(that.hsvInput[0].value), parseFloat(that.hsvInput[1].value), parseFloat(that.hsvInput[2].value));
            that.rgb = that.hsv.toRGB();
            that.hsl = that.hsv.toHSL();

            that.changeColor();
            that.reposition();
        };
    },
    /**
     * @name 设置颜色
     * @param {float} r Red分量，0~1
     * @param {float} g Green分量，0~1
     * @param {float} b Blue分量，0~1
     */
    setColor:function(r,g,b)
    {
        this.rgb = new RGB(r, g, b);
        this.hsl = this.rgb.toHSL();
        this.hsv = this.rgb.toHSV();

        this.changeColor();
        this.reposition();
    },

/*内部*/
    /**
     * @name 取色器触发
    */
    pickerActivate: function ()
    {
        this.rgb = this.hsv.toRGB();
        this.hsl = this.hsv.toHSL();

        this.changeColor();
    },
    /**
     * @name 改变颜色
     * @description 根据属性值改变颜色
     */
    changeColor:function()
    {
        var r = this.rgb.r, g = this.rgb.g, b = this.rgb.b;
        this.color.style.backgroundColor = "rgb(" + r + "," + g + "," + b + ")";
        var zero = Array(2).join('0');
        this.hexDisplay.innerHTML = "# " + (zero + r.toString(16)).slice(-2) + (zero + g.toString(16)).slice(-2) + (zero + b.toString(16)).slice(-2);
        this.rgbInput[0].value = r;
        this.rgbInput[1].value = g;
        this.rgbInput[2].value = b;

        this.hslInput[0].value = this.hsl.h.toFixed(2);
        this.hslInput[1].value = this.hsl.s.toFixed(2);
        this.hslInput[2].value = this.hsl.l.toFixed(2);

        this.hsvInput[0].value = this.hsv.h.toFixed(2);
        this.hsvInput[1].value = this.hsv.s.toFixed(2);
        this.hsvInput[2].value = this.hsv.v.toFixed(2);

        throttle(this, this.CallbackDelay, this.callback, {r:r,g:g,b:b});
    },
    /**
     * Marker重定位
     * @description 根据属性值重定位Marker
     */
    reposition:function()
    {
        this.markerWheel.style.transform="translate(-50%,-50%) rotate("+this.hsv.h+"deg)"; 
        this.mask.style.backgroundColor="hsl("+this.hsv.h+",100%,50%)";
        this.markerMask.style.left=this.hsv.s*this.MaskWidth+this.MaskLeft+"px";
        this.markerMask.style.top=(1-this.hsv.v)*this.MaskHeight+this.MaskTop+"px";
    },
    /**
     * 输入框回车
     * @param e {object} 事件对象
     */
    inputEnter:function(e)
    {
        if(e.keyCode==13)
            this.blur();
    },
    /**
     * 输入框失去焦点
     * @param e {object} 事件对象
     */
    inputBlur:function(e)
    {
        this.checkValue();
    },
    /**
     * 输入框获得焦点
     */
    inputFocus:function()
    {
        this.valuePreserve=this.value;
    },
    /**
     * markWheel鼠标移动处理函数
     * @description 注册到document
     * @param e 事件对象
     */
    markerWheel_handlerMouseMove:function(e)
    {
        var x = e.clientX - this.that.partPosition.left - this.that.PickerCenterX - this.that.PickerLeftOffset;
        var y = e.clientY - this.that.partPosition.top - this.that.PickerCenterY;
        var angle = Math.atan(y / x) / (2 * Math.PI) * 360;

        if (x < 0 && y >= 0)
            angle += 180;
        else if (x < 0 && y < 0)
            angle += -180;
        angle += 180;
        if (angle >= 0 && angle < 90)
            angle += 270;
        else
            angle -= 90;

        this.that.markerWheel.style.transform = "translate(-50%,-50%) rotate(" + angle + "deg)";        //旋转
        this.that.mask.style.backgroundColor = "hsl(" + angle + ",100%,50%)";

        this.that.hsv.h = angle;
        this.that.pickerActivate();
    },
    /**
     * markWheel鼠标抬起处理函数
     * @description 注册到document
     * @param e 事件对象
     */
    markerWheel_handlerMouseUp:function()
    {
        this.removeEventListener("mousemove", this.that.markerWheel_handlerMouseMove);
        this.removeEventListener("mouseup", this.that.markerWheel_handlerMouseUp);
    },
    /**
     * markMask鼠标移动处理函数
     * @description 注册到document
     * @param e 事件对象
     */
    markerMask_handlerMouseMove:function(e)
    {
        var x = parseInt(this.offsetLeft) + e.clientX - this.that.mouseX;
        var y = parseInt(this.offsetTop) + e.clientY - this.that.mouseY;

        if (x < this.that.MaskLeft)
            x = this.that.MaskLeft;
        else if (x > this.that.MaskRight)
            x = this.that.MaskRight;
        if (y < this.that.MaskTop)
            y = this.that.MaskTop;
        else if (y > this.that.MaskBottom)
            y = this.that.MaskBottom;

        this.style.left = x + "px";
        this.style.top = y + "px";

        this.that.mouseX = e.clientX;
        this.that.mouseY = e.clientY;

        this.that.hsv.s = (x - this.that.MaskLeft) / this.that.MaskWidth;
        this.that.hsv.v = 1 - (y - this.that.MaskTop) / this.that.MaskHeight;
        this.that.pickerActivate();
    },

    /**
     * markMask鼠标抬起处理函数
     * @description 注册到document
     * @param e 事件对象
     */
    markerMask_handlerMouseUp:function()
    {
        this.removeEventListener("mousemove", this.that.markerMask_handlerMouseMove);
        this.removeEventListener("mouseup", this.that.markerMask_handlerMouseUp);
    }
};

/**
 * 节流执行函数
 * @description 在一定时间内多次调用此函数，method只会在time时间后执行一次
 * @param {Function} method 函数 
 * @param {Object} context method执行环境，this指针对象
 * @param {int} time 延迟时间 
 * @param {any} ... 调用method 函数的参数
 */
function throttle(context, time, method)
{
    var methodArgumnets = [].slice.call(arguments, 3);
    clearTimeout(method.tId);
    method.tId = setTimeout(function ()
    {
        method.apply(context, methodArgumnets);
    }, time);
}

/**
 * @name RGB构造函数
 * @param {int} r 红色分量，0~255
 * @param {int} g 绿色分量，0~255
 * @param {int} b 蓝色分量，0~255
*/
function RGB(r,g,b)
{
    this.r = r;
    this.g = g;
    this.b = b;
}
RGB.prototype=
{
    constructor: RGB,

/*接口*/
    /**
     * @name 转换为HSL对象
     * @return {Object} HSL对象
    */
    toHSL:function()
    {
        var r = this.r / 255, g = this.g / 255, b = this.b / 255;
        if (r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1)
            return null;

        var max = r;
        if (g > max)
            max = g;
        if (b > max)
            max = b;
        var min = r;
        if (g < min)
            min = g;
        if (b < min)
            min = b;

        var h, s, l;

        if (max == min)
            h = 0;
        else if (max == r && g >= b)
            h = 60 * (g - b) / (max - min) + 0;
        else if (max == r && g < b)
            h = 60 * (g - b) / (max - min) + 360;
        else if (max == g)
            h = 60 * (b - r) / (max - min) + 120;
        else if (max == b)
            h = 60 * (r - g) / (max - min) + 240;

        l = (max + min) / 2;

        if (l == 0 || max == min)
            s = 0;
        else if (l > 0 && l <= 0.5)
            s = (max - min) / (2 * l);
        else if (l > 0.5)
            s = (max - min) / (2 - 2 * l);

        return new HSL( h, s, l);
    },

/**
 * @name 转换为HSV对象
 * @return {Object} HSV对象
*/
    toHSV:function()
    {
        var r = this.r / 255, g = this.g / 255, b = this.b / 255;
        if (r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1)
            return null;

        var max = r;
        if (g > max)
            max = g;
        if (b > max)
            max = b;
        var min = r;
        if (g < min)
            min = g;
        if (b < min)
            min = b;

        var h, s, v;

        if (max == min)
            h = 0;
        else if (max == r && g >= b)
            h = 60 * (g - b) / (max - min) + 0;
        else if (max == r && g < b)
            h = 60 * (g - b) / (max - min) + 360;
        else if (max == g)
            h = 60 * (b - r) / (max - min) + 120;
        else if (max == b)
            h = 60 * (r - g) / (max - min) + 240;

        if (max == 0)
            s = 0;
        else
            s = 1 - min / max;

        v = max;

        return new HSV(h,s,v);
    },
}

/**
 * @name HSL构造函数
 * @param {float} h 色相分量，0~1
 * @param {float} s 饱和度分量，0~1
 * @param {float} l 亮度分量，0~1
*/
function HSL(h,s,l)
{
    this.h = h;
    this.s = s;
    this.l = l;
}
HSL.prototype=
{
    constructor: HSL,

    /**
     * @name 转换为RGB对象
     * @return {Object} RGB对象
    */
    toRGB:function()
    {
        if (this.h < 0 || this.h > 359 || this.s < 0 || this.s > 1 || this.l < 0 || this.l > 1)
            return null;

        var temp1;
        if (this.l < 0.5)
            temp1 = this.l * (1 + this.s);
        else
            temp1 = this.l + this.s - (this.l * this.s);
        var temp2 = 2 * this.l - temp1;
        var hNormlized = this.h / 360;
        var tempRgb = new Array(3);
        tempRgb[0] = hNormlized + 1 / 3;
        tempRgb[1] = hNormlized;
        tempRgb[2] = hNormlized - 1 / 3;

        for (var i = 0; i < 3; i++)
        {
            if (tempRgb[i] < 0)
                tempRgb[i] += 1;
            else if (tempRgb[i] > 1)
                tempRgb[i] -= 1;
        }

        var rgb = new Array(3);
        for (var i = 0; i < 3; i++)
        {
            if (tempRgb[i] < 1 / 6)
                rgb[i] = temp2 + ((temp1 - temp2) * 6 * tempRgb[i]);
            else if (tempRgb[i] >= 1 / 6 && tempRgb[i] < 1 / 2)
                rgb[i] = temp1;
            else if (tempRgb[i] >= 1 / 2 && tempRgb[i] < 2 / 3)
                rgb[i] = temp2 + ((temp1 - temp2) * 6 * (2 / 3 - tempRgb[i]));
            else
                rgb[i] = temp2;
        }

        return new RGB(Math.floor(rgb[0]*255),Math.floor(rgb[1]*255),Math.floor(rgb[2]*255));
    },

    /**
     * @name 转换为HSV对象
     * @return {Object} HSV对象
    */
    toHSV:function()
    {
        if (this.h < 0 || this.h > 359 || this.s < 0 || this.s > 1 || this.l < 0 || this.l > 1)
            return null;

        var hHsv, sHsv, v;

        hHsv = this.h;

        if (this.l == 0)
        {
            sHsv = 0;
            v = 0;
        }
        else if (this.l > 0 && this.l <= 0.5)
        {
            sHsv = 2 * this.s / (1 + this.s);
            v = this.l * (1 + this.s);
        }
        else
        {
            sHsv = (2 * this.s - 2 * this.s * this.l) / (this.s - this.s * this.l + this.l);
            v = this.s - this.s * this.l + this.l;
        }

        return new HSV(hHsv,sHsv,v);
    }
}

/**
 * @name HSV构造函数
 * @param {float} h 色相分量，0~1
 * @param {float} s 饱和度分量，0~1
 * @param {float} v 明度分量，0~1
*/
function HSV(h,s,v)
{
    this.h = h;
    this.s = s;
    this.v = v;
}
HSV.prototype=
{
    constructor: HSV,

    /**
     * @name 转换为RGB对象
     * @return {Object} RGB对象
    */
    toRGB:function()
    {
        if (this.h < 0 || this.h > 359 || this.s < 0 || this.s > 1 || this.v < 0 || this.v > 1)
            return null;

        var tempH = Math.floor(this.h / 60);
        var temp1 = this.h / 60 - tempH;
        var temp2 = this.v * (1 - this.s);
        var temp3 = this.v * (1 - temp1 * this.s);
        var temp4 = this.v * (1 - (1 - temp1) * this.s);

        var rgb;
        switch (tempH)
        {
            case 0:
                rgb = { r: this.v, g: temp4, b: temp2 };
                break;
            case 1:
                rgb = { r: temp3, g: this.v, b: temp2 };
                break;
            case 2:
                rgb = { r: temp2, g: this.v, b: temp4 };
                break;
            case 3:
                rgb = { r: temp2, g: temp3, b: this.v };
                break;
            case 4:
                rgb = { r: temp4, g: temp2, b: this.v };
                break;
            case 5:
                rgb = { r: this.v, g: temp2, b: temp3 };
                break;
        }

        return new RGB(Math.floor(rgb.r * 255),Math.floor(rgb.g * 255),Math.floor(rgb.b * 255));
    },

    /**
     * @name 转换为HSL对象
     * @return {Object} HSL对象
    */
    toHSL:function()
    {
        if (this.h < 0 || this.h > 359 || this.s < 0 || this.s > 1 || this.v < 0 || this.v > 1)
            return null;

        var hHsl, sHsl, l;

        hHsl = this.h;

        if (this.v == 0)
        {
            sHsl = 0;
            l = 0;
        }
        else if (this.v <= 1 / (2 - this.s))
        {
            sHsl = this.s / (2 - this.s);
            l = (2 * this.v - this.v * this.s) / 2;
        }
        else if (this.s == 0 && this.v == 1)
        {
            sHsl = 1;
            l = 1;
        }
        else
        {
            sHsl = this.v * this.s / (2 - 2 * this.v + this.v * this.s);
            l = (2 * this.v - this.v * this.s) / 2;
        }

        return new HSL(hHsl,sHsl,l);
    }
}